﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Web;
using System.Web.Configuration;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace RRSClientWebApp
{
    // This sammple app template dynamically generates an ASP.NET page with input fields to call 
    // an AzureML RRS endpoint. It is meant to show the usage of RRS APIs. 
    
    //1. Update the Web.config file's AppSettings values with your web service info.
    //2. Add required references: Also need to add the following references:
    //      System.Net.Http
    //      System.Net.Http.Formatting
    //3. Run the app

    public partial class Default : System.Web.UI.Page
    {
        string webServicePostUrl;

        //The UI controls are added at run time when the page loads.
        protected void Page_Load(object sender, EventArgs e)
        {
            //Get the page header
            string pageTitle = WebConfigurationManager.AppSettings[0].ToString();
            lblAppName.Text = pageTitle;

            Util util = new Util();
            //Get the API URL from web.config file. 
            webServicePostUrl = WebConfigurationManager.AppSettings[1].ToString();
            string columnNames = util.getColumnsListFromAPIUrl(webServicePostUrl);

            //add the columns to the input form
            AddColumnsToInputForm(columnNames);
        }
        //Generat controls and add to the page at run time
        private void AddColumnsToInputForm(string columnList)
        {
            string[] colsArray = columnList.Split(',');
            for (int i = 0; i < colsArray.Length; i++)
            {
                AddControl(colsArray[i].ToString());
            }
        }
        //Field name is used to name the control.
        //The name is used later to dynamcially get the control's value and post to the service. 
        //This adds one row for each control with label(name of the field): textbox(value) <br/>
        private void AddControl(string name)
        {
            //label
            Label lbl = new Label();
            lbl.Text = name;
            lbl.ID = "lbl" + name;
            PlaceHolder1.Controls.Add(lbl);

            //colon
            Literal litColon = new Literal();
            litColon.Text = ": ";
            PlaceHolder1.Controls.Add(litColon);

            //textbox
            TextBox txt = new TextBox();
            txt.ID = name;
            PlaceHolder1.Controls.Add(txt);

            //line break
            Literal litLineBreak = new Literal();
            litLineBreak.Text = "<br/>";
            PlaceHolder1.Controls.Add(litLineBreak);
        }
        protected void btnSubmit_Click(object sender, EventArgs e)
        {
            //read the column names and values from the ui. will use it to create the json request.
            Dictionary<string, string> featureList = getColumnsAndValues();

            //set the corect post url (only post to original version)
            setPostURLString();

            //call RRS
            InvokeRequestResponseService(featureList).Wait();
        }
        //Check and adjust URL version if necessary
        private string setPostURLString()
        {
            //Version 2 of the API ends with exeucte. If passed in v2 URL, change to end with Score
            int idx = webServicePostUrl.IndexOf("/execute");
            if (idx > 0)
            {
                //remove everything after and including '/execute' and replace with '/score'
                string temp = webServicePostUrl.Substring(0, (webServicePostUrl.Length - (webServicePostUrl.Length - idx)));
                webServicePostUrl = temp + "/score";
            }
            return webServicePostUrl;
        }
        //Get the controls(columns) from the placeholder and get their values to submit to the API
        private Dictionary<string, string> getColumnsAndValues()
        {
            //var list = new List<KeyValuePair<string, string>>();
            var dict = new Dictionary<string, string>();
            foreach (Control control in PlaceHolder1.Controls)
            {
                string columnName = "";
                string columnValue = "";

                if (control.ID != null)
                {
                    columnName = control.ID;
                    if (control is TextBox || control is DropDownList)
                    {
                        if (control is TextBox)
                        {
                            TextBox txt = control as TextBox;
                            if (txt.Text != "")
                            {
                                columnValue = txt.Text;
                            }
                        }
                        if (control is DropDownList)
                        {
                            DropDownList lb = control as DropDownList;
                            if (lb.SelectedIndex != -1)
                            {
                                columnValue = lb.SelectedValue;
                            }
                        }
                        //add to list
                        dict.Add(columnName, columnValue);
                    }
                }
            }
            return dict;
        }
        //******************************************RRS Client code to submit request to server***************************************
        //This is copied from the help page sample code and modified for ASP.NEt
        private async Task InvokeRequestResponseService(Dictionary<string, string> columnsDictionary)
        {
            //Get the API Key from web.config.
            string webServiceKey = WebConfigurationManager.AppSettings[2].ToString();

            using (var client = new HttpClient())
            {
                ScoreData scoreData = new ScoreData()
                {
                    FeatureVector = columnsDictionary,
                    GlobalParameters = new Dictionary<string, string>()
                    {
                    }
                };

                ScoreRequest scoreRequest = new ScoreRequest()
                {
                    Id = "score00001",
                    Instance = scoreData
                };
                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", webServiceKey);


                client.BaseAddress = new Uri(webServicePostUrl);

                HttpResponseMessage response = await client.PostAsJsonAsync("", scoreRequest).ConfigureAwait(false);

                if (response.IsSuccessStatusCode)
                {
                    string apiResult = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
                    divResult.InnerText = "Result: " + apiResult;
                }
                else
                {
                    divResult.InnerText = string.Format("The request failed with status code: {0}", response.StatusCode);
                    // Print the headers - they include the requert ID and the timestamp, which are useful for debugging the failure
                    divResult.InnerText = response.Headers.ToString();
                    string responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
                    divResult.InnerText = responseContent;
                }
            }
        }
        public Dictionary<string, string> FeatureVector { get; set; }
        public Dictionary<string, string> GlobalParameters { get; set; }
        public class ScoreData
        {
            public Dictionary<string, string> FeatureVector { get; set; }
            public Dictionary<string, string> GlobalParameters { get; set; }
        }
        public class ScoreRequest
        {
            public string Id { get; set; }
            public ScoreData Instance { get; set; }
        }
    }
}
